/*
 * Copyright (c) 2018-2999 北京小象智慧信息科技有限公司 All rights reserved.
 *
 * https://www.xiaoxiangai.com/
 *
 * 未经允许，不可做商业用途！
 *
 * 版权所有，侵权必究！
 */

package com.yami.shop.admin.task;

import java.io.IOException;
import java.io.InputStream;
import java.security.KeyStore;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.util.*;

import cn.hutool.core.date.DateTime;
import com.yami.shop.admin.config.Constants;
import com.yami.shop.admin.config.PayUtil;
import com.yami.shop.admin.controller.RefundController;
import com.yami.shop.bean.model.*;
import com.yami.shop.service.*;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.collections.CollectionUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.yami.shop.bean.enums.OrderStatus;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.yami.shop.bean.pt.YxPtgl;
import com.yami.shop.service.IYxPtglService;
import com.yami.shop.bean.pt.YxPtsp;
import com.yami.shop.service.IYxPtspService;
import com.yami.shop.bean.pt.YxCtjl;
import com.yami.shop.service.IYxCtjlService;
import com.yami.shop.bean.model.Order;
import com.yami.shop.service.OrderService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;

import javax.net.ssl.SSLContext;


@Component("orderTask")
public class OrderTask {

    private  int socketTimeout = 9999999;// 连接超时时间，默认10秒
    private  int connectTimeout = 99999999;// 传输超时时间，默认30秒

    private  static RequestConfig requestConfig;// 请求器的配置

    private Logger logger = LoggerFactory.getLogger(getClass());

    private  static CloseableHttpClient httpClient;// HTTP请求器

    @Autowired
    private OrderService orderService;
    @Autowired
    private ProductService productService;
    @Autowired
    private SkuService skuService;
    @Autowired
    private RebateRecordsService rebateRecordsService;
    @Autowired
    private CashOutService cashOutService;
    @Autowired
    private IYxPtglService iYxPtglService;
    @Autowired
    private IYxPtspService iYxPtspService;
    @Autowired
    private IYxCtjlService iYxCtjlService;
    @Autowired
    private OrderSettlementService orderSettlementService;
    @Autowired
    private  SendMessageToUserService sendMessageToUserService;
    @Autowired
    private OrderRefundService orderRefundService;
    @Autowired
    private   CheckAccountService checkAccountService;
    @Autowired
    private ConfigService configService;
    @Autowired
    private UserDepositService userDepositService;



    public void cancelOrder() {
        Date now = new Date();
        logger.info("取消超时未支付订单。。。");
        // 获取30分钟之前未支付的订单
        List<Order> orders = orderService.listOrderNotPay(OrderStatus.UNPAY.value(), DateUtil.offsetMinute(now, -30));
        if (CollectionUtil.isEmpty(orders)) {
            return;
        }
        orderService.cancelOrders(orders);
        for (Order order : orders) {
            List<OrderItem> orderItems = order.getOrderItems();
            for (OrderItem orderItem : orderItems) {
                productService.removeProductCacheByProdId(orderItem.getProdId());
                skuService.removeSkuCacheBySkuId(orderItem.getSkuId(), orderItem.getProdId());
            }
        }
    }

    /**
     * 确认收货
     */
    public void confirmOrder() {
        Date now = new Date();
        logger.info("系统自动确认收货订单。。。");
        // 获取15天之前未支付的订单
        List<Order> orders = orderService.listOrderbyDvyTime(OrderStatus.CONSIGNMENT.value(), DateUtil.offsetDay(now, -3));
        if (CollectionUtil.isEmpty(orders)) {
            return;
        }
        orderService.confirmOrder(orders);
        for (Order order : orders) {
            List<OrderItem> orderItems = order.getOrderItems();
            for (OrderItem orderItem : orderItems) {
                productService.removeProductCacheByProdId(orderItem.getProdId());
                skuService.removeSkuCacheBySkuId(orderItem.getSkuId(), orderItem.getProdId());
            }
        }
    }
    /**
     * 拼团失败，取消订单，退款
     * */
    public void cancelGroupOrder(){
        List<Order> orders =orderService.groupFailOrders();
        if(CollectionUtil.isNotEmpty(orders)){
            for(Order order : orders){
                try{
                    //查询拼团订单有没有退款记录
                    OrderRefund orderRefund = orderRefundService.selectByOrderNumber(order.getOrderNumber());
                    if(orderRefund!=null) {
                        orderRefund.setRefundSts(2);
                        orderRefundService.saveOrUpdate(orderRefund);
                    }
                    dorefund(order.getOrderNumber());
                }catch (Exception e){
                    e.printStackTrace();
                }
            }
        }

    }

    /**
     * 确认收货超过3天后禁止申请售后(订单完成)
     */
    public void finishOrder() {
        Date now = new Date();
        logger.info("系统自动确认订单完成。。。");
        // 获取3天之前确认收货的订单
        List<Order> orders = orderService.listOrderAndOrderItems(OrderStatus.SUCCESS.value(), DateUtil.offsetDay(now, -3));
        if (CollectionUtil.isEmpty(orders)) {
            return;
        }
        orderService.finishOrder(orders);
        for (Order order : orders) {
            List<OrderItem> orderItems = order.getOrderItems();
            for (OrderItem orderItem : orderItems) {
                productService.removeProductCacheByProdId(orderItem.getProdId());
                skuService.removeSkuCacheBySkuId(orderItem.getSkuId(), orderItem.getProdId());
            }
        }
    }

    /**
     * 提现3个工作日后变为已到账状态
     */
    public void updateCashOutStatus() {
        Date now = new Date();
        logger.info("系统自动确认订单完成。。。");
        // 获取3天之前确认收货的订单
        List<CashOut> items = cashOutService.cashOutItems(0, DateUtil.offsetDay(now, -3));
        if (CollectionUtil.isEmpty(items)) {
            return;
        }
        for (CashOut cashOut : items) {
            Date approvalTime = cashOut.getApprovalTime();
            List<Date> dateList = findDates(approvalTime, now);
            int sum =0;
            for(Date date:dateList){
                Calendar cal = Calendar.getInstance();
                cal.setTime(date);
                if(cal.get(Calendar.DAY_OF_WEEK) == Calendar.SATURDAY || cal.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY){

                }else{
                    sum = sum + 1;
                }
            }
            //更新提现状态为已提现状态
            if(sum >=3){
                cashOut.setState(3);
                cashOutService.saveOrUpdate(cashOut);
            }
        }
    }

    /**
     * 待成团订阅消息提醒
     */
    public void sendMessageToUser(){
        Date now = new Date();
        //查询当前未成团的记录
        List<YxPtgl> yxPtglList = iYxPtglService.getNotSuccessedList(DateUtil.offsetHour(now,-8));
        System.out.println("chauxunptjieguo");
        if(CollectionUtils.isNotEmpty(yxPtglList)){
                for(YxPtgl yxPtgl:yxPtglList){
                  //向未成团的用户发送订阅消息
                    sendMessageToUserService.pushNotSuccessPT(yxPtgl);
                }
        }
    }

    /**
     * 根据设定的时间入账
     */
    public void enterAccount(){
        Date now = new Date();
        //根据设定的入账时间查询订单,直接入账这些订单
        String time = configService.getValue("enter_account_time");
        StringBuffer buffer = new StringBuffer();
        buffer.append("-").append(time);
        //查询前一天的订单
        DateTime dateTime =DateUtil.offsetDay(now,Integer.parseInt(buffer.toString()));
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        String yesterday = sdf.format(dateTime);
        List<Order> orderList = orderService.getOrderListByEnterTime(yesterday);
        if(CollectionUtils.isNotEmpty(orderList)){
            for(Order order:orderList){
                //查询当前订单有没有入账
                String orderNumber = order.getOrderNumber();
                CheckAccount checkAccount = checkAccountService.getByOrderNumber(orderNumber);
                if(checkAccount==null) {
                    checkAccountService.dealOrderByTime(order);
                }
            }
        }
    }

    /**
     * 根据充值金额扣除推广费用(3个月之后入账)
     */
    public void enterPromoteFee(){
        Date now = new Date();
        //根据设定的充值金额入账时间,将钱加到指定商家账户
        String time = configService.getValue("enter_promote_fee_time");
        StringBuffer buffer = new StringBuffer();
        buffer.append("-").append(time);
        List<UserDeposit> userDepositList = userDepositService.getUserDepositList(DateUtil.offsetDay(now,Integer.parseInt(buffer.toString())));
        if(CollectionUtils.isNotEmpty(userDepositList)){
            for(UserDeposit userDeposit:userDepositList){
                userDepositService.updatePromoteFee(userDeposit);

            }
        }

    }



    /**
     * 获取一个时间段中的日期
     */

    public List<Date> findDates(Date approvalTime, Date dEnd) {
        Date dBegin = DateUtil.offsetDay(approvalTime,+1);
        List lDate = new ArrayList();
        lDate.add(dBegin);
        Calendar calBegin = Calendar.getInstance();
        // 使用给定的 Date 设置此 Calendar 的时间
        calBegin.setTime(dBegin);
        Calendar calEnd = Calendar.getInstance();
        // 使用给定的 Date 设置此 Calendar 的时间
        calEnd.setTime(dEnd);
        // 测试此日期是否在指定日期之后
        while (dEnd.after(calBegin.getTime())) {
            // 根据日历的规则，为给定的日历字段添加或减去指定的时间量
            calBegin.add(Calendar.DAY_OF_MONTH, 1);
            lDate.add(calBegin.getTime());
        }
        return lDate;


    }
    private  String getRandomStringByLength(int length) {
        String base = "abcdefghijklmnopqrstuvwxyz0123456789";
        Random random = new Random();
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < length; i++) {
            int number = random.nextInt(base.length());
            sb.append(base.charAt(number));
        }
        return sb.toString();
    }


    //具体的调用微信的退款接口
    @GetMapping("/dorefund")
    @ApiOperation(value = "退款方法", notes = "根据订单金额退款")
    @ApiImplicitParams({
    })
    public void dorefund(String orderNumber) throws Exception{
        String code = Constants.CODE_SUCCESS;//状态码
        String msg = Constants.REFUND_SUCCESS;//提示信息
        Map <String,String> data = new HashMap<String,String>();
        String  orderId = "";

        try {
            OrderSettlement settlement = orderSettlementService.getSettlementByOrderId(orderNumber);
            //退款到用户微信
            String nonce_str = getRandomStringByLength(32);
            //data.put("userId", "7c7c3c98526646c3b07d7928d9f25399");
            data.put("appid", Constants.appID);
            data.put("mch_id", Constants.MCH_ID);
            data.put("nonce_str", nonce_str);
            data.put("sign_type", "MD5");
            data.put("out_trade_no", settlement.getPayNo());//商户订单号
            data.put("out_refund_no",  settlement.getPayNo());//商户退款单号
            //Math.round(userecord.getMoney() * 100);
            data.put("total_fee",String.valueOf(Math.round(settlement.getPayAmount()*100)));//支付金额，微信支付提交的金额是不能带小数点的，且是以分为单位,这边需要转成字符串类型，否则后面的签名会失败
            data.put("refund_fee", String.valueOf(Math.round(settlement.getPayAmount()*100)));//退款总金额,订单总金额,单位为分,只能为整数
//                data.put("notify_url", Constants.NOTIFY_URL_REFUND);//退款成功后的回调地址
            String preStr = PayUtil.createLinkString(data); // 把数组所有元素，按照“参数=参数值”的模式用“&”字符拼接成字符串
            //MD5运算生成签名，这里是第一次签名，用于调用统一下单接口
            String mySign = PayUtil.sign(preStr, Constants.key, "utf-8").toUpperCase();
            data.put("sign", mySign);

            //拼接统一下单接口使用的xml数据，要将上一步生成的签名一起拼接进去
            String pjxml = PayUtil.GetMapToXML(data);
            System.out.println(pjxml);
            String xmlStr = postData(Constants.REFUND_PATH, PayUtil.GetMapToXML(data)); //支付结果通知的xml格式数据
            System.out.println(xmlStr);
            Map notifyMap = PayUtil.doXMLParse(xmlStr);
            if ("SUCCESS".equals(notifyMap.get("return_code"))) {
                if("SUCCESS".equals(notifyMap.get("result_code"))) {
                    //退款成功的操作
                    String prepay_id = (String) notifyMap.get("prepay_id");//返回的预付单信息
                    System.out.println(prepay_id);
                    Long timeStamp = System.currentTimeMillis() / 1000;
                    //拼接签名需要的参数
                    String stringSignTemp = "appId=" + Constants.appID + "&nonceStr=" + nonce_str + "&package=prepay_id=" + prepay_id + "&signType=MD5&timeStamp=" + timeStamp;
                    //签名算法生成签名
                    String paySign = PayUtil.sign(stringSignTemp, Constants.key, "utf-8").toUpperCase();
                    data.put("package", "prepay_id=" + prepay_id);
                    data.put("timeStamp", String.valueOf(timeStamp));
                    data.put("paySign", paySign);
                }else{
                    System.out.println("退款失败:原因"+notifyMap.get("return_msg"));
                    code = Constants.CODE_ERROR;
                    msg = (String)notifyMap.get("return_msg");
                }
            }else{
                System.out.println("退款失败:原因"+notifyMap.get("return_msg"));
                code = Constants.CODE_ERROR;
                msg = (String)notifyMap.get("return_msg");
            }
        }catch (Exception e) {
            code = Constants.CODE_ERROR;
            msg = Constants.MSG_01;
        }
        Map <String,Object> jsonResult = new HashMap<String,Object>();
        jsonResult.put("code",code);
        jsonResult.put("msg",msg);
        jsonResult.put("data",data);
    }

    public  String postData(String url, String xmlObj) {
        // 加载证书
        try {
            initCert();
        } catch (Exception e) {
            e.printStackTrace();
        }
        String result = null;
        HttpPost httpPost = new HttpPost(url);
        // 得指明使用UTF-8编码，否则到API服务器XML的中文不能被成功识别
        StringEntity postEntity = new StringEntity(xmlObj, "UTF-8");
        httpPost.addHeader("Content-Type", "text/xml");
        httpPost.setEntity(postEntity);
        // 根据默认超时限制初始化requestConfig
        requestConfig = RequestConfig.custom()
                .setSocketTimeout(socketTimeout)
                .setConnectTimeout(connectTimeout)
                .build();
        // 设置请求器的配置
        httpPost.setConfig(requestConfig);
        try {
            HttpResponse response = null;
            try {
                response = httpClient.execute(httpPost);
            }  catch (IOException e) {
                e.printStackTrace();
            }
            HttpEntity entity = response.getEntity();
            try {
                result = EntityUtils.toString(entity, "UTF-8");
            }  catch (IOException e) {
                e.printStackTrace();
            }
        } finally {
            httpPost.abort();
        }
        return result;
    }

    /**
     * 加载证书
     *
     */
    @PostMapping("/initCert")
    @ApiOperation(value = "加载证书", notes = "根据文件路径加载证书")
    private static void initCert() throws Exception {
        // 证书密码，默认为商户ID
        String key = Constants.MCH_ID;
        // 商户证书的路径
        //String path = Constants.CERT_PATH;
        //String filePath = RefundController.class.getClassLoader().getResource("apiclient_cert.p12").getFile();
        InputStream instream=RefundController.class.getResourceAsStream("/apiclient_cert.p12");
        // 指定读取证书格式为PKCS12
        KeyStore keyStore = KeyStore.getInstance("PKCS12");

        // 读取本机存放的PKCS12证书文件
        //FileInputStream instream = new FileInputStream(new File(filePath));
        try {
            // 指定PKCS12的密码(商户ID)
            keyStore.load(instream, key.toCharArray());
        } finally {
            instream.close();
        }

        SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore, key.toCharArray()).build();

        // 指定TLS版本
        SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext, new String[] { "TLSv1" }, null,SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
        // 设置httpclient的SSLSocketFactory
        httpClient = HttpClients.custom().setSSLSocketFactory(sslsf).build();
    }

}
